package com.resifind.www.service.impl;

import com.resifind.www.constant.*;
import com.resifind.www.dao.*;
import com.resifind.www.dao.impl.*;
import com.resifind.www.exception.*;
import com.resifind.www.po.*;
import com.resifind.www.service.OrderService;
import com.resifind.www.util.JdbcUtils;

import java.sql.Connection;
import java.util.List;

/**
 * @author 36069
 */
public class OrderServiceImpl implements OrderService {
    private final ClientDao clientDao = new ClientDaoImpl();
    private final OrderDao orderDao = new OrderDaoImpl();
    private final MerchantDao merchantDao = new MerchantDaoImpl();
    private final RoomDao roomDao = new RoomDaoImpl();
    private final BlacklistDao blacklistDao = new BlacklistDaoImpl();

    @Override
    public Resp<List<Order>> queryOrderByUserId(int userId, String userType) {
        if (userType.equals(UserTypes.CLIENT)) {
            Client client = clientDao.queryClientByUserId(userId);
            if (client != null) {
                List<Order> orders = orderDao.queryOrderByUserId(client.getId(), userType);
                return Resp.success(orders);
            } else {
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } else if (userType.equals(UserTypes.MERCHANT)) {
            Merchant merchant = merchantDao.queryMerchantByUserId(userId);
            if (merchant != null) {
                List<Order> orders = orderDao.queryOrderByUserId(merchant.getId(), userType);
                return Resp.success(orders);
            } else {
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } else {
            throw UserException.userTypeError();
        }
    }

    @Override
    public Resp<String> orderRoom(int clientId, int roomId, int roomNumberId) {
        //检查房间是否可用
        RoomNumber roomNumber = roomDao.queryRoomNumberByRoomNumberId(roomNumberId);
        if (roomNumber.getStatus().equals(RoomStatus.UNAVAILABLE)) {
            throw MerchantException.roomNotAvailable();
        }
        //获取房型信息
        Room room = roomDao.queryRoomByRoomId(roomId);
        //获取商家信息
        Merchant merchant = merchantDao.queryMerchantByRoomId(roomId);
        //检查商家是否拉黑该客户
        if (blacklistDao.queryBlacklistExist(clientId, merchant.getId(), BlacklistTypes.MERCHANT_LIST)) {
            throw BlacklistAndFavourException.blacklisted();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //创建订单
            boolean creatResult = orderDao.creatOrder(clientId, room, merchant.getId(), roomNumberId, conn);
            //更新房间的状态为不可用
            boolean updateRoomNumberResult = roomDao.updateRoomNumberStatus(roomNumberId, RoomStatus.UNAVAILABLE, conn);
            //更新房型销量和剩余数量
            boolean updateRoomSalesResult = roomDao.updateRoomSalesAndSurplus(roomId, 1, conn);
            //更新商家总销量
            boolean updateMerchantSalesResult = merchantDao.updateTotalSales(merchant.getId(), 1, conn);
            if (creatResult && updateRoomSalesResult && updateMerchantSalesResult && updateRoomNumberResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> cancelOrder(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        if (order == null) {
            throw OrderException.orderNotFound();
        }
        //只有待支付的订单才能取消
        if (!order.getTradeStatus().equals(TradeStatus.UNPAID)) {
            throw OrderException.orderCannotCanceled();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为已取消
            boolean cancelOrderResult = orderDao.updateOrderTradeStatus(orderId, TradeStatus.CANCELLED, conn);
            //更新房间的状态为可用
            boolean updateRoomNumberResult = roomDao.updateRoomNumberStatus(order.getRoomNumberId(), RoomStatus.AVAILABLE, conn);
            //更新房型销量和剩余数量
            boolean updateRoomSalesResult = roomDao.updateRoomSalesAndSurplus(order.getRoomId(), -1, conn);
            //更新商家总销量
            boolean updateMerchantSalesResult = merchantDao.updateTotalSales(order.getMerchantId(), -1, conn);
            if (cancelOrderResult && updateRoomSalesResult && updateMerchantSalesResult && updateRoomNumberResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> applyRefund(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        //判断订单状态是否为已支付且未入住
        boolean flag = order.getTradeStatus().equals(TradeStatus.PAID) && order.getCheckStatus().equals(CheckStatus.NOT_CHECKED_IN);
        if (!flag) {
            throw OrderException.orderCannotRefund();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为退款中
            boolean updateTradeResult = orderDao.updateOrderTradeStatus(orderId, TradeStatus.REFUNDING, conn);
            if (updateTradeResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> checkIn(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        //判断订单状态是否为已支付且未入住
        boolean flag = order.getTradeStatus().equals(TradeStatus.PAID) && order.getCheckStatus().equals(CheckStatus.NOT_CHECKED_IN);
        if (!flag) {
            throw OrderException.orderNotCheckIn();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为已入住
            boolean updateCheckResult = orderDao.updateOrderCheckStatus(orderId, CheckStatus.NORMAL, conn);
            if (updateCheckResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> checkOut(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        //判断订单状态是否为已支付且已入住
        boolean flag = order.getTradeStatus().equals(TradeStatus.PAID) && order.getCheckStatus().equals(CheckStatus.NORMAL);
        if (!flag) {
            throw OrderException.orderCannotCheckout();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为已退房
            boolean updateCheckResult = orderDao.updateOrderCheckStatus(orderId, CheckStatus.CHECKED_OUT, conn);
            //更新房间的状态为可用
            boolean updateRoomNumberResult = roomDao.updateRoomNumberStatus(order.getRoomNumberId(), RoomStatus.AVAILABLE, conn);
            if (updateCheckResult && updateRoomNumberResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> deleteOrder(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        boolean flag = (order.getTradeStatus().equals(TradeStatus.PAID) && !order.getCheckStatus().equals(CheckStatus.CHECKED_OUT))
                || order.getTradeStatus().equals(TradeStatus.REFUNDING);
        if (flag) {
            //已支付但不是已退房, 或退款中的订单，不允许删除
            throw OrderException.orderNotComplete();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            boolean deleteOrderResult = orderDao.fakeDeleteOrderByOrderId(orderId, conn);
            if (deleteOrderResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> payOrder(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        //判断订单状态是否为待支付
        if (!order.getTradeStatus().equals(TradeStatus.UNPAID)) {
            throw OrderException.orderAlreadyPaid();
        }
        //判断客户余额是否充足
        Client client = clientDao.queryClientByClientId(order.getClientId());
        if (client.getBalance() < order.getAmount()) {
            throw ClientException.balanceNotEnough();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为已支付
            boolean updateTradeResult = orderDao.updateOrderTradeStatus(orderId, TradeStatus.PAID, conn);
            double amount = order.getAmount();
            //客户余额减去订单金额
            boolean updateBalanceResult = clientDao.updateBalance(order.getClientId(), -1 * amount, conn);
            //商家营业额加上订单金额
            boolean updateTurnoverResult = merchantDao.updateTurnover(order.getMerchantId(), amount, conn);
            if (updateTradeResult && updateBalanceResult && updateTurnoverResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> refund(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        //判断订单状态是否为退款中
        if (!order.getTradeStatus().equals(TradeStatus.REFUNDING)) {
            throw OrderException.orderCannotRefund();
        }
        //根据商户id获取商户信息
        Merchant merchant = merchantDao.queryMerchantByMerchantId(order.getMerchantId());
        //判断商家营业额是否不足
        if (merchant.getTurnover() < order.getAmount()) {
            throw MerchantException.turnoverNotEnough();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为已退款
            boolean updateTradeResult = orderDao.updateOrderTradeStatus(orderId, TradeStatus.REFUNDED, conn);
            //更新房间状态为可用
            boolean updateRoomNumberResult = roomDao.updateRoomNumberStatus(order.getRoomNumberId(), RoomStatus.AVAILABLE, conn);
            double amount = order.getAmount();
            //客户余额加上订单金额
            boolean updateBalanceResult = clientDao.updateBalance(order.getClientId(), amount, conn);
            //商家营业额减去订单金额
            boolean updateTurnoverResult = merchantDao.updateTurnover(order.getMerchantId(), -1 * amount, conn);
            //更新房型销量和剩余数量
            boolean updateRoomSalesResult = roomDao.updateRoomSalesAndSurplus(order.getRoomId(), -1, conn);
            //更新商家总销量
            boolean updateMerchantSalesResult = merchantDao.updateTotalSales(order.getMerchantId(), -1, conn);
            if (updateTradeResult && updateBalanceResult && updateTurnoverResult && updateRoomNumberResult && updateRoomSalesResult && updateMerchantSalesResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> refuseRefund(int orderId) {
        //获取订单信息
        Order order = orderDao.queryOrderByOrderId(orderId);
        //判断订单状态是否为退款中
        if (!order.getTradeStatus().equals(TradeStatus.REFUNDING)) {
            throw OrderException.orderCannotRefund();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //更新订单状态为已支付
            boolean updateTradeResult = orderDao.updateOrderTradeStatus(orderId, TradeStatus.PAID, conn);
            if (updateTradeResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }
}
